package sites.manager.common.config;

import com.alibaba.druid.filter.stat.StatFilter;
import com.alibaba.druid.wall.WallFilter;
import com.jfinal.aop.Aop;
import com.jfinal.config.*;
import com.jfinal.ext.handler.ContextPathHandler;
import com.jfinal.ext.interceptor.SessionInViewInterceptor;
import com.jfinal.kit.Prop;
import com.jfinal.kit.PropKit;
import com.jfinal.plugin.activerecord.ActiveRecordPlugin;
import com.jfinal.plugin.druid.DruidPlugin;
import com.jfinal.plugin.druid.DruidStatViewHandler;
import com.jfinal.plugin.druid.IDruidStatViewAuth;
import com.jfinal.plugin.ehcache.EhCachePlugin;
import com.jfinal.template.Engine;
import sites.manager.admin.site.SiteService;
import sites.manager.common.kit.SiteInfo;
import sites.manager.common.model._MappingKit;

import javax.servlet.http.HttpServletRequest;
import java.sql.Connection;

public class SiteConfig  extends JFinalConfig {

    private static Prop p;
    private WallFilter wallFilter;
    private StatFilter statFilter;

    /**
     * 加载主配置文件
     */
    static void loadConfig() {
        if (p == null) {
            p = PropKit.use("siteConfig.txt");
            // 如果存在生产版本的配置文件则追加，更好地区分开发环境和生产环境
            p.appendIfExists("siteConfig-pro.txt");
        }
    }

    @Override
    public void configConstant(Constants constants) {
        loadConfig();
        constants.setDevMode(p.getBoolean("devMode", false));
        constants.setError404View("/view/error/404.html");
        constants.setError500View("/view/error/500.html");
        constants.setMaxPostSize(100 * 1024 * 1024);

        // 支持 Controller、Interceptor、Validator 之中使用 @Inject 注入业务层，并且自动实现 AOP
        constants.setInjectDependency(true);
        // 切换到 cglib 对 proxy 模块的实现
        constants.setToCglibProxyFactory();
    }

    @Override
    public void configRoute(Routes routes) {
        routes.add(new AdminRoutesConfig());
        routes.add(new ApiRoutesConfig());
    }

    @Override
    public void configEngine(Engine engine) {
        engine.setDevMode(true);
        engine.addSharedObject("SiteInfo", new SiteInfo());
    }

    @Override
    public void configPlugin(Plugins plugins) {
        // 配置DruidPlugin
        DruidPlugin druidPlugin = getDruidPlugin();
        wallFilter = new WallFilter(); // 加强数据库安全
        wallFilter.setDbType("mysql");
        druidPlugin.addFilter(wallFilter);
        statFilter = new StatFilter();// 配置数据监控
        statFilter.setMergeSql(true);
        statFilter.setLogSlowSql(true);
        statFilter.setSlowSqlMillis(1500);
        druidPlugin.addFilter(statFilter); // 添加 StatFilter 才会有统计数据
        plugins.add(druidPlugin);

        // 配置ActiveRecordPlugin
        ActiveRecordPlugin arp = new ActiveRecordPlugin(druidPlugin);
        arp.setTransactionLevel(Connection.TRANSACTION_READ_COMMITTED);
        arp.setShowSql(p.getBoolean("devMode", false));
        arp.getEngine().setToClassPathSourceFactory();
        arp.addSqlTemplate("/sql/all.sql");
        _MappingKit.mapping(arp);
        plugins.add(arp);

        // 启用缓存插件
        plugins.add(new EhCachePlugin());
    }

    public static DruidPlugin getDruidPlugin() {
        loadConfig();
        String jdbcUrl = p.get("jdbcUrl").trim();
        String user = p.get("user").trim();
        String password = p.get("password").trim();
        String driverClass = p.get("driverClass").trim();

        DruidPlugin druidPlugin = new DruidPlugin(jdbcUrl, user, password, driverClass, "config");// config是固定的，这个是JFinal要求的，有这个标记才会进行数据库密码的加解密
        druidPlugin.setPublicKey(p.get("publicKey").trim());

        return druidPlugin;
    }

    @Override
    public void configInterceptor(Interceptors interceptors) {
        /*
         * 配置session过滤，JFinal默认是不支持session传递数据的，配置后才能在页面获取session中存放的数据
         * 有这个配置后还可以在自定义指令中通过scope.get("session")获取session
         */
        interceptors.add(new SessionInViewInterceptor());
    }

    @Override
    public void configHandler(Handlers handlers) {
        handlers.add(new ContextPathHandler("ctx"));// 这个是设置上下文路径的

        // 使用JFinal的方式配置druid内置监控视图
        handlers.add(new DruidStatViewHandler("/druid", new IDruidStatViewAuth() {
            public boolean isPermitted(HttpServletRequest request) {
                return true;
            }
        }));
    }

    @Override
    public void onStart() {
        System.out.println("当前版本：" + SiteInfo.version);
        System.out.println("当前版本更新时间：" + SiteInfo.updateDate);

        // 初始化主站点信息
        Aop.get(SiteService.class).initSiteInfo();
    }
}
